/*
 * Copyright (C) 2008 Peter Kling
 * 
 * This file is part of 'A Kind of Billiard', a graphical billiard simulation.
 * 
 * 'A Kind of Billiard' is free software: you can redistribute it and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 * 
 * 'A Kind of Billiard' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with 'A Kind of Billiard'. If not, see
 * <http://www.gnu.org/licenses/>.
 */

package de.akob.particles;

import javax.media.opengl.GL;

import de.akob.mathematics.MathVector;
import de.akob.mathematics.Mathematics;

public class SmokeParticleEngine extends ParticleEngine {
	
	public SmokeParticleEngine() {
	}
	
	public SmokeParticleEngine(int numberParticles, double slowDown, double size, double xPos, double yPos,
	        double zPos, double xGravity, double yGravity, double zGravity, int[] randomGravity) {
		super(numberParticles, slowDown, size, xPos, yPos, zPos, xGravity, yGravity, zGravity, randomGravity);
	}
	
	@Override
	public double getTime() {
		return time;
	}
	
	@Override
	protected Particle[] initializeParticles() {
		Particle[] particles = new Particle[numberParticles];
		for (int i = 0; i < numberParticles; i++) {
			particles[i] = new SmokeParticle(this);
			particles[i].setRandomGravity(new int[] { xRandom, yRandom, zRandom });
			particles[i].setXGravity(xGravity);
			particles[i].setYGravity(yGravity);
			particles[i].setZGravity(zGravity);
		}
		return particles;
	}
	
	@Override
	public void updateParticles(GL gl) {
		time = (time + 0.02f) % Math.PI * 2;
		// store several OpenGL state variables
		gl.glPushAttrib(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_LIGHTING_BIT | GL.GL_TEXTURE_BIT);
		gl.glPushMatrix();
		
		gl.glEnable(GL.GL_DEPTH_TEST);
		gl.glDepthMask(false);
		gl.glDisable(GL.GL_LIGHTING);
		gl.glEnable(GL.GL_BLEND);
		gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
		
		gl.glEnable(GL.GL_TEXTURE_2D);
		gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
		
		MathVector position;
		double[] viewMatrix = new double[16];
		gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, viewMatrix, 0);
		MathVector right = new MathVector(3);
		right.set(1, viewMatrix[0]);
		right.set(2, viewMatrix[4]);
		right.set(3, viewMatrix[8]);
		
		MathVector up = new MathVector(3);
		up.set(1, viewMatrix[1]);
		up.set(2, viewMatrix[5]);
		up.set(3, viewMatrix[9]);
		
		// Partikelpumpe
		MathVector addRightUp = Mathematics.add(right, up);
		MathVector subRightUp = Mathematics.sub(right, up);
		MathVector subUpRight = Mathematics.sub(up, right);
		
		// Move to the right place:
		gl.glTranslated(xPos, yPos, zPos);
		for (int i = 0; i < numberParticles; i++) {
			if (particles[i].isAlive()) {
				double size = particles[i].getSize() / 2;
				position = particles[i].getPosition();
				// Setze Farbe des Partikels
				gl.glColor4d(particles[i].getRed(), particles[i].getGreen(), particles[i].getBlue(), particles[i]
				        .getLife());
				// Zeichne Partikel
				gl.glBegin(GL.GL_QUADS);
				gl.glTexCoord2d(0, 0);
				MathVector v = Mathematics.add(position, Mathematics.mul(addRightUp, -size));
				gl.glVertex3d(v.get(1), v.get(2), v.get(3));// (x+viewMatrix[0],y+viewMatrix[4],z+viewMatrix[8]);
				gl.glTexCoord2d(1, 0);
				v = Mathematics.add(position, Mathematics.mul(subRightUp, size));
				gl.glVertex3d(v.get(1), v.get(2), v.get(3));
				gl.glTexCoord2d(1, 1);
				v = Mathematics.add(position, Mathematics.mul(addRightUp, size));
				gl.glVertex3d(v.get(1), v.get(2), v.get(3));
				gl.glTexCoord2d(0, 1);
				v = Mathematics.add(position, Mathematics.mul(subUpRight, size));
				gl.glVertex3d(v.get(1), v.get(2), v.get(3));
				gl.glEnd();
				// Update Partikel:
				// Bewegung: Addiere Bewegungsterm mit SlowdownFaktor
				
			}
			particles[i].moveParticle();
		}
		
		// restore saved OpenGL state
		gl.glPopAttrib();
		gl.glPopMatrix();
		
	}
}
